#pragma once
#include "IRealTimeDealModel.h"
#include "../BondMarketStream.h"
#include "../bondlib.h"
#include "../BondInfo.h"
#include "../SSVContainer.h"
#include <stdint.h>
#include <vector>
#include <map>
#include <mutex>
#include <core/sync/lock.h>

namespace detail{
	class CBondDealJumpList;
	class RealTimeDealCache;
	class RealTimeDealStat;
	class RealTimeDealList;
}
struct MarkStreamListArg{
	int					corp;
	int					mark_type;
	int					page_type;//emMktStreamPage
	std::vector<uint32_t>		days;
	MarkStreamListArg() :corp(-1), mark_type(-1), page_type(-1){}
};
struct MarketStreamTopArg{
	int					count;
	int					mark_type;
	std::vector<uint32_t>		days;
	MarketStreamTopArg() :count(10), mark_type(-1){}
};
struct MarketStreamInfoArg{
	int					stat_type;
	int					mark_type;
	std::vector<uint32_t>		days;
	MarketStreamInfoArg() :stat_type(-1), mark_type(-1){}
};
class S_BONDLIB_EXPORT CMarketStream : public CMarketStreamBase{
	enum{ OBJECT_TAG = 0xf1f2f3f4 };
	typedef int			BatchId;
	typedef uint32_t		DayType;

	typedef std::mutex CSLock;
	typedef std::lock_guard<std::mutex> ScopedCSLock;
    typedef std::map<DayType, int64_t> DayStateMap;
protected:
	typedef detail::RealTimeDealList RTDealList;
    typedef std::map<DayType, RTDealList*> DayDealMap;
public:
	typedef std::list<MarketStreamInfo> MSInfoList;
	typedef std::map<std::string, MarketStreamRec> MSRecMap;
	struct ParsedStreamInfo{
		uint32_t								unDay;
		CMarketStreamBase::kStreamType		type;
		MarketStreamInfo					info;
	};
public://共用枚举定义已经迁移到CMarketStreamBase中
protected:
	// 用于检测当前对象的合法性,合法对象必须是固定值
	unsigned int		m_tag;

	// 用于按天保存当天的成交信息,通常是当天的成交信息最多
	DayDealMap			m_deal_map;
	DayStateMap			m_deal_states;

	// GetOrCreateList中用于保存上次查找结果,加快GetOrCreateList速度;
	// 如果给定day与此结果的日期相等,那么立即返回
	RTDealList*			m_last;

	// 每此收到的E_FID_QB_MARKET_STREAM_DEAL_PUSH消息对应的xQBMarketStreamList_c*
	// 称为一个批次,保存到m_keys中
	// 界面中收到通知后,与此底层数据同步索引,也会更新批次id
	// 两者的批次id用于表示处理成交记录信息的各自进度
	BatchId				m_nextid;
	qb::base::Mutex		m_lock;
public:
	struct EnumeratorArg{
		CMarketStream*	object;
		uint32_t				day;
	};
	class Enumerator;
	typedef const Enumerator* ConstEnumPtr;
	class S_BONDLIB_EXPORT iterator{
		ConstEnumPtr	m_enumerator;
		int				m_index;
	public:
		iterator() :m_enumerator(0), m_index(-1){}//为了CMarketStreamDebug::iterator
		iterator(int index, ConstEnumPtr enumerator) :m_index(index), m_enumerator(enumerator){}
		iterator(const iterator& it) :m_index(it.m_index), m_enumerator(it.m_enumerator){}
		iterator& operator = (const iterator& it){ m_index = it.m_index; m_enumerator=it.m_enumerator; return *this; }
		const MarketStreamInfo& operator*()const;
		const MarketStreamInfo* operator->()const;
		bool operator==(const iterator& it)const{ return m_enumerator == it.m_enumerator && m_index == it.m_index; }
		bool operator!=(const iterator& it)const{ return m_index != it.m_index || m_enumerator != it.m_enumerator; }
		iterator& operator++(){ m_index++; return *this; }
	};
	class S_BONDLIB_EXPORT Enumerator{
		std::vector<DealIndex>	m_indexes;
		IRecordMap*			m_values;
		detail::RealTimeDealStat* m_stats;
	//	ScopedCSLock		m_scoped;
		friend class iterator;
	private:
		Enumerator();
		Enumerator(const Enumerator& e);
		Enumerator& operator=(const Enumerator& e);
	public:
		explicit Enumerator(CMarketStream* object, uint32_t day,bool all=false);
		~Enumerator(){}
        bool findrec(const std::string& combBondKey, MarketStreamRec& rec)const;
		iterator begin()const;
		iterator end()const{ return iterator(m_indexes.size(),this); }
	protected:
		const MarketStreamInfo& GetAt(int nIndex)const;
	};
public:
	static CMarketStream& cfectsStream();
	static CMarketStream& exchangeStream();
	static CMarketStream& bondStream();

	void	Save(){}
	bool	Clear(uint32_t uTime = 0);
public://兼容接口
//	std::mutex& GetMutex(){ return m_lock; }
	void	RefreshKeyToContainer(CSSVContainer* pssv, char* pszCorp);

	//获取MarketStreamInfo
	bool	GetMarketStreamByKey(const char * szCombBondKey, const char * szKey, MarketStreamInfo &stInfo, uint32_t timeDay = 0);
	bool    GetMarketStreamByBrokers(const std::vector<BrokerKey>& brokerKeys, std::vector<MarketStreamInfo>& records, time_t t = 0, uint32_t day = 0);

	bool	GetMarketStreamStatByKey(const char * szCombBondKey, MarketStreamRec& stat, uint32_t timeDay = 0);

	//获取Broker对应中与时间接近的MarketStream
	bool GetNearByMarketStream(const char* pBondCombKey, time_t t, const char* pBrokerId, MarketStreamInfo& info, uint32_t timeDay = 0);


	// 经过调查,以下使用到了CMarketStreamlst.m_Record信息
	bool	GetTFRelativeStream(CMarketStreamlst &Marketlist, uint32_t timeDay = 0);
	bool	GetInterestRateStream(CMarketStreamlst &Marketlist, uint32_t timeDay = 0);
	bool	GetCreditRateStream(CMarketStreamlst &Marketlist, uint32_t timeDay = 0, bool bNeedNCD = false/*是否含NCD*/);


	// 经过调查以下接口中并没有使用到CMarketStreamlst.m_Record信息
	bool	GetLastDayMSByCorp(int nCorp, CMarketStreamlst& mktLst);

	bool	GetMarketInfoByType(CMarketStreamlst &Marketlist, MarktType mkType, uint32_t timeDay = 0);
	bool	GetMarketInfoByType(CMarketStreamlst &Marketlist, MarktType mkType, const std::vector<uint32_t>& timeVector);//子窗口成交

	bool	GetInterestRateStream(CMarketStreamlst &Marketlist, const std::vector<uint32_t>& timeVector);//利率债成交
	bool	GetCreditRateStream(CMarketStreamlst &Marketlist, const std::vector<uint32_t>& timeVector, bool bNeedNCD = false/*是否含NCD*/);//信用债成交
	
	//获取CMarketToprec
	//bool	GetMarketRecord(CMarketToprec &MarketInfo,uint32_t timeDay = 0);
	//bool	GetMarketActvTrans(CMarketToprec &MarketInfo,MarktType mkType,uint32_t timeDay = 0);                
	bool	GetMarketRecord(CMarketToprec &MarketInfo, const std::vector<uint32_t>& timeVector, uint32_t nActvNum = 10);                      //成交概览 -- 活跃成交
	static bool	GetTodayMarketRecord(CMarketToprec &MarketInfo, const CMarketStreamlst &lst, uint32_t nActvNum = 10);                     //获取当天活跃成交
	bool	GetMarketActvTrans(CMarketToprec &MarketInfo, MarktType mkType, const std::vector<uint32_t>& timeVector, uint32_t nActvNum = 10);  //子窗口 -- 活跃成交

	//获取CMarketInfoMap
	bool	GetMarketInfoByType(CMarketInfoMap &MarketInfo, const std::vector<uint32_t>& timeVector);//成交概览 -- 成交分布-- 按新QB产品类型分类，即地方债、国债、央票、金融债、短融、中票、企业债、其他
	bool	GetMarketInfoByType(CMarketInfoMap &MarketInfo, uint32_t timeDay = 0);
	bool	GetMarketInfoByDate(CMarketInfoMap &MarketInfo, const std::vector<uint32_t>& timeVector);//成交概览 -- 成交分布-- 每条柱为当日某一特定剩余期限范围内的所有债券成交记录的笔数
	bool	GetMarketInfoByDate(CMarketInfoMap &MarketInfo, uint32_t timeDay = 0);

	bool	GetMarketTransDate(CMarketInfoMap &MarketInfo, MarktType mkType, const std::vector<uint32_t>& timeVector);  //国债 -- 成交分布
	bool	GetMarketTransDate(CMarketInfoMap &MarketInfo, MarktType mkType, uint32_t timeDay = 0);

	bool	GetMarketRatioByType(CMarketInfoMap &MarketInfo, MarktType mkType, const std::vector<uint32_t>& timeVector);//其他 -- 成交分布
	bool	GetMarketRatioByType(CMarketInfoMap &MarketInfo, MarktType mkType, uint32_t timeDay = 0);


	bool	GetMarketTransRating(CMarketInfoMap &MarketInfo, MarktType mkType, const std::vector<uint32_t>& timeVector);//短融,中票，企业债，城投债 -- 成交分布
	bool	GetMarketTransRating(CMarketInfoMap &MarketInfo, MarktType mkType, uint32_t timeDay = 0);

	bool	GetMarketTransNFRate(CMarketInfoMap &MarketInfo, MarktType mkType, const std::vector<uint32_t>& timeVector);//浮息债 -- 成交分布
	bool	GetMarketTransNFRate(CMarketInfoMap &MarketInfo, MarktType mkType, uint32_t timeDay = 0);

public://获取成交信息,共有6大接口
	// 获取某家Broker最后一笔成交version
	int GetVersion(int companyID);

	// 用于快速获取一屏的当日实时成交信息
	int GetRecords(IRealTimeDealModel* keys, int& pos, int count, void* records);

	// 获取指定债券的单个成交信息,或者多个（GetBondDealBatch）
	bool GetBondDeal(const char * szCombBondKey, const char* szCompanyId, MarketStreamInfo& record, time_t t = 0, uint32_t day = 0);
	bool GetBondDealBatch(const std::vector<BrokerKey>& brokerKeys, std::vector<MarketStreamInfo>& records, time_t t = 0, uint32_t day = 0);

	// 用于过滤成交信息
	bool GetMarketStreamList(const MarkStreamListArg& arg, MSInfoList& mkList, MSRecMap* mkRecordMap = NULL);

	// 用于获取排名靠前的成交信息
	bool GetTopRecords(const MarketStreamTopArg& arg,CMarketToprec &MarketInfo);

	// 用于获取成交数据的计数统计信息
	bool GetMarketInfo(const MarketStreamInfoArg& arg, CMarketInfoMap& infoMap);
public://导入成交信息
	void InsertCashData(xQBMarketStreamList_c* pLstdata, bool& ret);
	void InsertCFETSCashData(xQBMarketStreamList_c* pLstdata, uint32_t DealType, bool& ret);
	RTDealList* GetList(DayType day);// 外界不要使用,仅供CMarketStreamDebug
protected:
	bool IsObjectValid()const;
	RTDealList* GetOrCreateList(DayType day);
	CMarketStream();
	virtual ~CMarketStream();
public:
	static bool IsBondPassType(const CBondInfo& bond, MarktType type);
	static bool IsBondPassPage(const CBondInfo& bond, emMktStreamPage pageType);
	static int GetMarketInfoKey(int stat, int mktType, const CBondInfo& bond);
	static bool IsDealValid(const xQBMarketStreamUnit_c& msu, uint32_t& unDay, kStreamType& type);
	static bool FilterDealList(xQBMarketStreamList_c* pLstdata, std::vector<ParsedStreamInfo>& batch);
	static bool FilterCFETSDealList(xQBMarketStreamList_c* pLstdata, std::vector<ParsedStreamInfo>& batch, uint32_t DealType);
	static bool UpdateMarketInfoMap(const MarketStreamInfo& record, int mktype, int stattype, CMarketInfoMap& infoMap);
};
